/********** 层次性数据 **********/
function pair(x, y) {
  return {
    head: x,
    tail: y,
  };
}

function head(z) {
  return z.head;
}
function tail(z) {
  return z.tail;
}
function list(...items) {
  return items.reverse().reduce((a, b) => pair(b, a), null);
}
function listRef(items, i) {
  if (i === 0) return head(items);
  return listRef(tail(items), i - 1);
}
// 练习：递归转迭代
function length(items) {
  if (isNull(items)) return 0;
  return 1 + length(tail(items));
}
function append(list1, list2) {
  if (isNull(list1)) return list2;
  return pair(head(list1), append(tail(list1), list2));
}
function lastPair(items) {
  if (isNull(tail(items))) return items;
  return lastPair(tail(items));
}
// 练习：递归转迭代
// [1, [2, [3, [4, null]]]]
function reverse(items) {
  if (isNull(items)) return null;
  return append(reverse(tail(items)), pair(head(items), null));
}

function reverse2(items) {
  return reverseIter(items);

  function reverseIter(items, result = null) {
    if (isNull(items)) return result;
    return reverseIter(tail(items), pair(head(items), result));
  }
}
function map(items, fn) {
  if (isNull(items)) return null;
  return pair(fn(head(items)), map(tail(items), fn));
}

function squareList1(items) {
  return iter(items);

  function iter(items, result = null) {
    if (isNull(items)) return result;
    return iter(tail(items), pair(head(items) ** 2, result));
  }
}
function squareList2(items) {
  return iter(items);

  function iter(items, result = null) {
    if (isNull(items)) return result;
    return iter(tail(items), pair(result, head(items) ** 2));
  }
}
function squareList3(items) {
  return iter(items);

  function iter(items, result = null) {
    if (isNull(items)) return reverse(result);
    return iter(tail(items), pair(head(items) ** 2, result));
  }
}
const m = list(1, 3, 5, 7, 9);
const n = list(2, 4, 6, 8, 0);

// print(reverse(m));

function print(...args) {
  args.forEach(arg => console.log(JSON.stringify(arg)));
}

function isNull(target) {
  return target === null;
}

module.exports = {
  pair,
  head,
  tail,
  list,
  reverse: reverse2,
  map,
  append,
  isNull,
};
